package com.cqfae.deploycentral.app.services.impl;

import com.cqfae.deploycentral.api.utils.IdGenerator;
import com.cqfae.deploycentral.app.base.BaseConstantCode;
import com.cqfae.deploycentral.app.base.BaseConstants;
import com.cqfae.deploycentral.app.config.DeployInfo;
import com.cqfae.deploycentral.app.config.JenkinsInfo;
import com.cqfae.deploycentral.app.config.PinganGwInfo;
import com.cqfae.deploycentral.app.config.WebSocketInfo;
import com.cqfae.deploycentral.app.dao.entity.DeployHistory;
import com.cqfae.deploycentral.app.dao.entity.ReportInfo;
import com.cqfae.deploycentral.app.dao.entity.WindowPlansTag;
import com.cqfae.deploycentral.app.dao.mapper.DeployHistoryMapper;
import com.cqfae.deploycentral.app.dao.mapper.ReportInfoMapper;
import com.cqfae.deploycentral.app.dao.mapper.WindowPlansTagMapper;
import com.cqfae.deploycentral.app.services.DeployHistoryService;
import com.cqfae.deploycentral.app.services.JenkinsService;
import com.cqfae.deploycentral.app.services.RemoteService;
import com.cqfae.deploycentral.app.utils.ConvertUtil;
import com.cqfae.deploycentral.app.utils.GsonUtils;
import com.cqfae.deploycentral.app.utils.NullUtil;
import com.cqfae.deploycentral.app.web.enums.DeployPercentEnum;
import com.cqfae.deploycentral.app.web.enums.ProgressColorEnum;
import com.cqfae.deploycentral.app.web.request.DeployActionRequest;
import com.cqfae.deploycentral.app.web.request.JenkinsNotifyRequest;
import com.cqfae.deploycentral.app.web.request.PinganGwRequest;
import com.cqfae.deploycentral.app.web.response.IPage;
import com.cqfae.deploycentral.app.web.response.MailResponse;
import com.cqfae.deploycentral.app.web.vo.DeployHistoryVo;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.google.gson.reflect.TypeToken;
import org.apache.commons.lang3.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import tk.mybatis.mapper.entity.Example;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * Created by YANGHENG940 on 2017/7/24.
 */
@Service
@Transactional
public class DeployHistoryServiceImpl implements DeployHistoryService {

    private static Logger logger = LoggerFactory.getLogger(DeployHistoryServiceImpl.class);


    @Autowired
    private IdGenerator idGenerator;

    @Autowired
    private DeployHistoryMapper deployHistoryMapper;

    @Autowired
    private JenkinsInfo jenkinsInfo;

    @Autowired
    private WindowPlansTagMapper windowPlansTagMapper;

    @Autowired
    private PinganGwInfo pinganGwInfo;

    @Autowired
    private RemoteService remoteService;

    @Autowired
    private ReportInfoMapper reportInfoMapper;

    @Autowired
    private DeployInfo deployInfo;

    @Autowired
    private SimpMessagingTemplate messagingTemplate;

    @Autowired
    private WebSocketInfo webSocketInfo;

    @Autowired
    private JenkinsService jenkinsService;

    @Override
    public DeployHistory updateByCallBack(JenkinsNotifyRequest request) {
        Assert.isTrue(NullUtil.isNotEmpty(request.getBuildId())
                && NullUtil.isNotEmpty(request.getStatus())
                && NullUtil.isNotEmpty(request.getCallBackId()), "The request param is null !");
        DeployHistory dhsUpdate = new DeployHistory();
        dhsUpdate.setId(request.getCallBackId());
        dhsUpdate = deployHistoryMapper.selectOne(dhsUpdate);

        DeployHistory dhsInster = new DeployHistory();
        BeanUtils.copyProperties(dhsUpdate, dhsInster);
        dhsInster.setId(idGenerator.nextId());
        dhsInster.setBuildId(request.getBuildId());
        dhsInster.setBuildLogUrl(ConvertUtil.createJenkinsLogUrl(jenkinsInfo.getHost(), dhsUpdate.getAppName(), request.getBuildId()));
        dhsInster.setCreateBy("123");
        dhsInster.setCreateTime(new Date());
        dhsInster.setDeployStatus(request.getStatus());
        if (request.getStatus() == BaseConstantCode.DEPLOY_ROLLBACK_FAIL || request.getStatus() == BaseConstantCode.DEPLOY_ROLLBACK_SUCCESS) {
            //新增发布回滚历史数据
            deployHistoryMapper.insert(dhsInster);
            return dhsInster;
        }
        WindowPlansTag wintag = new WindowPlansTag();
        wintag.setId(dhsUpdate.getWindowPlansTagId());
        //更新窗口计划TAG状态
        wintag.setDeployStatus(request.getStatus());
        wintag.setUpdateBy("123");
        wintag.setUpdateTime(new Date());
        int i = windowPlansTagMapper.updateByPrimaryKeySelective(wintag);
        Assert.isTrue(i == 1, "update Window Plans TAG status Fail，id: " + dhsUpdate.getWindowPlansTagId());
        //新增发布历史数据
        deployHistoryMapper.insert(dhsInster);
        return dhsInster;
    }

    @Override
    public DeployHistoryVo changeDeployStatusAndMail(DeployHistoryVo vo) {
        boolean isError = ArrayUtils.contains(new int[]{
                BaseConstantCode.JENKINS_STATUS_GIT_FAIL,
                BaseConstantCode.JENKINS_STATUS_BUILD_FAIL,
                BaseConstantCode.JENKINS_STATUS_INPUT_FAIL,
                BaseConstantCode.JENKINS_STATUS_OUTPUT_FAIL,
                BaseConstantCode.JENKINS_STATUS_DEPLOY_FAIL,
                BaseConstantCode.JENKINS_STATUS_CHECK_FAIL}, vo.getDeployStatus());
        vo.setDeployStatusName(BaseConstants.getConstantsCodeMap().get(String.valueOf(vo.getDeployStatus())));
        // 设置执行百分比
        vo.setExecutePercent(DeployPercentEnum.value(vo.getDeployStatus()));
        // 设置颜色
        vo.setProgressColor(ProgressColorEnum.value(vo.getDeployStatus()));
        PinganGwRequest request = new PinganGwRequest();
        String mark = "【部署中心-";
        request.setAddressTo(pinganGwInfo.getAddressTo());
        if (isError) {
            if ("true".equals(deployInfo.getContinual())) {
                request.setTitle(mark + vo.getAppName() + "-发布失败】");
                vo.setDeployStatus(BaseConstantCode.DEPLOY_STATUS_FAIL);
                request.setContent(getMailContent(vo));
                MailResponse mailResponse = remoteService.sendMailToTester(pinganGwInfo.getLogSend(), request);
                logger.info("==== Fail Send Mail ===={}", GsonUtils.getInstance().toJson(mailResponse));
                messagingTemplate.convertAndSend(webSocketInfo.getSubscribe(), GsonUtils.getInstance().toJson(vo));
                String logJson2 = GsonUtils.getInstance().toJson(vo);
                logger.info("==== Continual send msg to web :==== {}", logJson2);
                // 继续调用Jenkins
                jenkinsService.invokeJenkins(vo.getReportCode());
            } else {
                request.setTitle(mark + vo.getAppName() + "-发布失败,所有任务将终止】");
                messagingTemplate.convertAndSend(webSocketInfo.getSubscribe(), GsonUtils.getInstance().toJson(vo));
                String logJson2 = GsonUtils.getInstance().toJson(vo);
                logger.info("==== Not Continual send msg to web :==== {}", logJson2);
            }
        } else if (BaseConstantCode.JENKINS_STATUS_CHECK_OK == vo.getDeployStatus().intValue()) {
            vo.setDeployStatus(BaseConstantCode.DEPLOY_STATUS_SUCCESS);
            request.setTitle(mark + vo.getAppName() + "-发布成功】");
            request.setContent(getMailContent(vo));
            MailResponse mailResponse = remoteService.sendMailToTester(pinganGwInfo.getLogSend(), request);
            logger.info("==== Success Send Mail ===={}", GsonUtils.getInstance().toJson(mailResponse));
            messagingTemplate.convertAndSend(webSocketInfo.getSubscribe(), GsonUtils.getInstance().toJson(vo));
            String logJson2 = GsonUtils.getInstance().toJson(vo);
            logger.info("==== Success send msg to web :==== {}", logJson2);
            // 继续调用Jenkins
            jenkinsService.invokeJenkins(vo.getReportCode());
        } else {
            messagingTemplate.convertAndSend(webSocketInfo.getSubscribe(), GsonUtils.getInstance().toJson(vo));
            String logJson2 = GsonUtils.getInstance().toJson(vo);
            logger.info("==== Success send msg to web :==== {}", logJson2);
        }
        return vo;
    }

    private String getMailContent(DeployHistoryVo vo) {
        StringBuilder sbd = new StringBuilder();
        ReportInfo info = new ReportInfo();
        info.setReportCode(vo.getReportCode());
        info = reportInfoMapper.selectOne(info);
        sbd.append("TAG：" + vo.getTag() + "\n");
        sbd.append("状态：" + vo.getDeployStatusName() + "\n");
        sbd.append("测试报告：" + info.getTitle() + "\n");
        sbd.append("此邮件由【部署中心】自动发送，请勿直接回复此邮件！");
        return sbd.toString();
    }


    /**
     * 翻页查询
     *
     * @param request
     * @return
     * @throws Exception
     */
    @Override
    public IPage<DeployHistoryVo> listByPage(DeployActionRequest request) {
        // 创建翻页对象
        Page<DeployHistoryVo> page = PageHelper.startPage(request.getPageNum(), request.getPageSize());
        // 组装查询条件
        Example example = new Example(DeployHistory.class);
        example.setOrderByClause("CREATE_TIME DESC");
        if (request.getBeginDate() > 0 || request.getEndDate() > 0) {
            Assert.isTrue(request.getEndDate() >= request.getBeginDate(), "日期不合法，请检查开始结束日期");
            SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd HH:mm:ss");
            Date startDate = null;
            Date endDate = null;
            try {
                startDate = df.parse(request.getBeginDate() + " 00:00:00");
                endDate = df.parse(request.getEndDate() + " 23:59:59");
            } catch (ParseException pe) {
                logger.warn("=======DeployHistoryServiceImpl.listByPage======{}", pe);
            }
            example.createCriteria().andBetween("createTime", startDate, endDate);
        }
        // 查询并设置数据
        deployHistoryMapper.selectByExample(example);
        IPage<DeployHistoryVo> ipage = ConvertUtil.pageToIpage(page, new IPage<DeployHistoryVo>());
        // 转换VO
        List<DeployHistoryVo> result = GsonUtils.getInstance().fromJson(GsonUtils.getInstance().toJson(page), new TypeToken<List<DeployHistoryVo>>() {
        }.getType());
        for (DeployHistoryVo vo : result) {
            // 验证编码
            codeCheck(vo);
            setCodeName(vo);
        }
        // 设置返回数据
        ipage.setResult(result);
        return ipage;
    }

    /**
     * 验证编码
     *
     * @param object
     */
    private void codeCheck(Object object) {
        if (object.getClass() == DeployHistoryVo.class) {
            DeployHistoryVo vo = (DeployHistoryVo) object;
            Assert.isTrue(NullUtil.isNotEmpty(BaseConstants.getConstantsCodeMap().get(String.valueOf(vo.getDeployStatus()))),
                    "发布状态码不存在：" + vo.getDeployStatus());
        }
    }

    /**
     * 设置code对应的name
     *
     * @param vo
     * @return
     */
    private DeployHistoryVo setCodeName(DeployHistoryVo vo) {
        vo.setDeployStatusStr(BaseConstants.getConstantsCodeMap().get(String.valueOf(vo.getDeployStatus())));
        return vo;
    }
}
